package cn.lingyangwl.agile.system.controller;

import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.lingyangwl.agile.auth.*;
import cn.lingyangwl.agile.auth.model.rqrs.ldp.*;
import cn.lingyangwl.agile.file.excel.*;
import cn.lingyangwl.agile.model.constants.*;
import cn.lingyangwl.agile.model.enums.*;
import cn.lingyangwl.agile.model.module.config.*;
import cn.lingyangwl.agile.model.module.config.param.*;
import cn.lingyangwl.agile.ram.*;
import cn.lingyangwl.agile.system.assembly.*;
import cn.lingyangwl.agile.system.model.rqrs.config.*;
import cn.lingyangwl.agile.system.service.*;
import cn.lingyangwl.agile.tenant.core.utils.*;
import cn.lingyangwl.framework.core.response.*;
import cn.lingyangwl.framework.security.xss.core.*;
import cn.lingyangwl.framework.tool.core.*;
import cn.lingyangwl.framework.validation.group.*;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import java.util.List;

/**
 * 参数配置 信息操作处理
 * @author shenguangyang
 */
@Tag(name = "参数配置")
@Validated
@RestController
@RequestMapping("/config")
public class SysConfigController {
    @Resource
    private SysConfigService configService;
    @Resource
    private SysConfigAssembly configAssembly;
    @Resource
    private AuthApi authApi;

    @ApiOperation(value = "获取使用的配置")
    @GetMapping("/getUseConfig")
    public Resp<ConfigInfo> getUseConfig(@RequestParam("configDefine") String configDefine) {
        return Resp.ok(configService.getUseConfig(ConfigDefineEnum.valueOf(configDefine)));
    }

    @ApiOperation(value = "获取参数配置列表")
    @GetMapping("/page")
    @RamResource(action = "sys:config:query", name = "查询配置", type = ActionType.READ)
    public Resp<IPage<ConfigResp>> pageConfig(@Validated ConfigPageReq req) {
        return Resp.ok(configService.pageConfig(req));
    }

    @RamResource(action = "sys:config:export", name = "导出配置", type = ActionType.READ)
    @PostMapping("/export")
    public void export(HttpServletResponse response, ConfigPageReq req) throws Exception {
        List<ConfigResp> list = configService.list(req);
        ExportParams params = new ExportParams();
        params.setType(ExcelType.HSSF);
        CusExcelExportUtil.exportExcel(response, params, "参数数据.xls", ConfigResp.class, list);
    }

    @Operation(summary = "通过id获取配置参数")
    @GetMapping("/getConfigById")
    @RamResource(action = "sys:config:query", name = "查询配置", type = ActionType.READ)
    public Resp<ConfigResp> getConfigById(@RequestParam("id") Long id) {
        ConfigResp config = configService.getConfigById(id);
        return Resp.ok(config);
    }

    @Operation(summary = "通过key获取配置参数")
    @GetMapping("/getConfigByKey")
    @RamResource(action = "sys:config:query", name = "查询配置", type = ActionType.READ)
    public Resp<ConfigResp> getConfigByKey(@RequestParam("configKey") String configKey) {
        ConfigResp config = configService.getConfig(new ConfigGetReq(configKey).setIsDesensitization(true));
        return Resp.ok(config);
    }

    /**
     * 可以匿名访问
     */
    @Operation(summary = "通过配置key获取配置参数")
    @GetMapping("/open/getConfigByKey")
    public Resp<ConfigResp> getConfigByKey(@RequestHeader(value = SecurityCons.FROM_SOURCE, required = false) String fromSource,
                                          @NotEmpty(message = ValidationCons.NOT_EMPTY)  @RequestParam(value = "configKey", required = false) String configKey) {
        ConfigKeyEnum configType = ConfigKeyEnum.of(configKey);
        if (!SecurityCons.FROM_IN.equals(fromSource)) {
            configType.checkCanAnonymousAccess();
        }
        ConfigResp resp = configService.getConfig(new ConfigGetReq(configKey));
        return Resp.ok(resp);
    }

    /**
     * 获取公共配置参数
     * @param clientId oauth2的客户端id
     * @param isolateData 如果为false, webSite只查询平台的, 否则根据传递的租户id查询
     */
    @Operation(summary = "获取初始化配置")
    @GetMapping("/open/initConfig")
    public Resp<InitConfigResp> initConfig(
        @RequestParam(value = "clientId", required = false) String clientId,
        @RequestParam(value = "isolateData", required = false, defaultValue = "false") Boolean isolateData
    ) {
        InitConfigResp configResp = TenantUtils.execute(TenantCons.SYSTEM_TENANT_ID, () -> {
            InitConfigResp resp = new InitConfigResp();
            // 查找网站版本配置信息(查找平台版权, 非平台租户不可自定义)
            ConfigKeyEnum configType = ConfigKeyEnum.COPYRIGHT;
            ConfigResp config = configService.getConfig(new ConfigGetReq(configType.getKey()));
            resp.setCopyright(BaseConfigParam.jsonToObject(configType.getKey(), config.getConfigValue()));

            // 查找客户端绑定的身份源
            if (StringUtils.isNotEmpty(clientId)) {
                List<ExtLdpConnectResp> ldpConnectList = authApi.listLdpConnectByClientId(clientId);
                resp.setLdpConnectList(ldpConnectList);
            }
            return resp;
        });

        // 查找web配置, 根据前端传递的租户id过滤
        ConfigKeyEnum configType = ConfigKeyEnum.WEB_SITE;
        ConfigResp config = configService.getConfig(new ConfigGetReq(configType.getKey()));

        WebSiteParam webSite = BaseConfigParam.jsonToObject(configType.getKey(), config.getConfigValue());
        configResp.setWebSite(configAssembly.toWebSite(webSite));
        configResp.setDefaultImage(configAssembly.toDefaultImage(webSite));

        return Resp.ok(configResp);
    }


    @Operation(summary = "保存-参数配置")
    @PostMapping("/save")
    @RamResource(action = "sys:config:save", name = "保存配置", type = ActionType.WRITE)
    @XssCleanIgnore({"paramDefine", "remark", "paramConfig"})
    public Resp<?> save(@Validated @RequestBody ConfigSaveReq req) {
        return Resp.ok(configService.saveConfig(req));
    }

    /**
     * 只能更新展示的配置(在配置列表中展示的配置)* @return
     */
    @Operation(summary = "更新-参数配置")
    @PostMapping("/update")
    @RamResource(action = "sys:config:update", name = "更新配置", type = ActionType.WRITE)
    @XssCleanIgnore({"paramDefine", "remark", "paramConfig"})
    public Resp<?> updateById(@Validated(UpdateGroup.class) @RequestBody ConfigUpdateReq req) {
        return Resp.ok(configService.updateConfig(req));
    }

    @Operation(summary = "更新-参数")
    @PostMapping("/updateConfigParam")
    @RamResource(action = "sys:configParam:update", name = "更新配置参数", type = ActionType.WRITE)
    @XssCleanIgnore({"remark", "configValue"})
    public Resp<?> updateParamConfig(@RequestBody @Validated ConfigParamUpdateReq req) {
        configService.updateConfigParam(req);
        return Resp.ok();
    }

    @Operation(summary = "批量删除-参数配置")
    @DeleteMapping("/deleteBatch")
    @RamResource(action = "sys:config:delete", name = "删除配置", type = ActionType.WRITE)
    public Resp<?> deleteBatch(@RequestParam(value = "ids") List<Long> ids) {
        return Resp.ok(configService.deleteConfigByIds(ids));
    }

    @Operation(summary = "删除-参数配置")
    @DeleteMapping("/delete")
    @RamResource(action = "sys:config:delete", name = "删除配置", type = ActionType.WRITE)
    public Resp<?> delete(@RequestParam(value = "id") Long id) {
        return Resp.ok(configService.deleteConfigById(id));
    }


    @Operation(summary = "刷新参数缓存")
    @RamResource(action = "sys:config:refreshCache", name = "刷新配置缓存", type = ActionType.WRITE)
    @DeleteMapping("/refreshCache")
    public Resp<?> refreshCache() {
        configService.resetConfigCache();
        return Resp.ok();
    }

    @Operation(summary = "查询敏感配置")
    @RamResource(action = "sys:config:querySensitiveConfig", name = "查询敏感的配置", type = ActionType.READ)
    @GetMapping("/getSensitiveConfig")
    public Resp<ConfigResp> getSensitiveConfig(@Validated SensitiveConfigGetReq req) {
        return Resp.ok(configService.getSensitiveConfig(req));
    }
}